package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.heima.common.aliyun.GreenImageScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.feign.article.ArticleFeign;
import com.heima.file.service.FileStorageService;
import com.heima.model.article.pojo.ApArticle;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.search.dto.ArticleDto;
import com.heima.model.wemedia.dto.WmNewsTransferDto;
import com.heima.model.wemedia.pojo.WmNews;
import com.heima.model.wemedia.pojo.WmSensitive;
import com.heima.model.wemedia.pojo.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.config.RabbitMqConfig;
import com.heima.wemedia.mapper.WmChannelMapper;
import com.heima.wemedia.mapper.WmNewsMapper;
import com.heima.wemedia.mapper.WmSensitiveMapper;
import com.heima.wemedia.mapper.WmUserMapper;
import com.heima.wemedia.service.WmNewSVerfiyService;
import com.heima.utils.common.ContentPaeser;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class WmNewSVerfiyServiceImpl implements WmNewSVerfiyService {
    @Autowired
    private GreenImageScan greenImageScan;
    @Autowired
    private GreenTextScan greenTextScan;
    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private WmNewsMapper wmNewsMapper;
    @Autowired
    private WmUserMapper wmUserMapper;
    @Autowired
    private ArticleFeign articleFeign;
    @Autowired
    private WmChannelMapper wmChannelMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Override
    public void verfiy(WmNews wmNews) throws Exception {
        //解析文章中文本和图片信息
        String content = wmNews.getContent();
        String contentText = ContentPaeser.getContentText(content);
        List<String> contentImages = ContentPaeser.getContentImages(content);
        //将内容图和封面图添加至set集合
        Set<String> imageSet = new HashSet<String>(contentImages);
        //获取封面图片
        String coverImages = wmNews.getImages();
        if (StringUtils.isNotEmpty(coverImages)){
            String[] images = coverImages.split(",");
            Collections.addAll(imageSet,images);
        }

        //自管理的敏感词过滤
        boolean isSensitive = handleSensitiveScan(contentText, wmNews);
        if(!isSensitive) {
            return;
        }
        //进行文本审核
        Boolean testVerify = testVerify(wmNews, contentText);
        if (!testVerify) {
            return;
        }
        //如果文本审核通过进行图片审核
        boolean imageVerify = imageVerify(wmNews, imageSet);
        if (!imageVerify) {
            return;
        }
        //审核通过判断发布时间和当前时间的关系
        if (wmNews.getPublishTime().after(new Date())){
            //发布时间大于当前时间则延迟发布,修改状态为8
            wmNews.setStatus(WmNews.Status.SUCCESS.getCode());
            wmNews.setReason("文章审核通过待发布");
            wmNewsMapper.updateById(wmNews);
            //发送消息到rabbitMQ延迟消息队列
            //获取文章id放入消息中
            Integer id = wmNews.getId();
            //设置延迟时间(待发布时间-当前系统时间)
            long ttl = wmNews.getPublishTime().getTime() - System.currentTimeMillis();
            Message message = MessageBuilder.withBody(String.valueOf(id).getBytes()).setExpiration(String.valueOf(ttl)).build();
            rabbitTemplate.convertAndSend(RabbitMqConfig.SEND_QUEUE_NAME,message);

        }else {
            //远程调用文章微服务，保存APP端文章
            Long articleId = publishArticle(wmNews);
            //发送消息,同步es
            //封装ArticleDto作为消息进行发送
            ArticleDto article = new ArticleDto();
            article.setId(String.valueOf(wmNews.getArticleId()));
            article.setPublishTime(wmNews.getPublishTime());
            article.setLayout(Integer.valueOf(wmNews.getType()));
            article.setImages(wmNews.getImages());
            //静态url用feign远程调用文章微服务查询
            ApArticle apArticle = articleFeign.findById(wmNews.getArticleId());
            article.setStaticUrl(apArticle.getStaticUrl());
            Integer userId = wmNews.getUserId();
            article.setAuthorId(userId.longValue());
            WmUser wmUser = wmUserMapper.selectById(userId);
            String name = wmUser.getName();
            article.setAuthorName(name);
            article.setTitle(wmNews.getTitle());
            String contentText1 = ContentPaeser.getContentText(content);
            article.setContent(contentText1);
            //发送消息
            kafkaTemplate.send("topicB", String.valueOf(articleId), JSON.toJSONString(article));


        }
    }

    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;

    /**
     * 发布文章
     *
     * @param wmNews
     * @return
     */
    @Override
    public Long publishArticle(WmNews wmNews) {
        WmNewsTransferDto transferDto = new WmNewsTransferDto();
        BeanUtils.copyProperties(wmNews,transferDto);
        Integer userId = wmNews.getUserId();
        WmUser wmUser = wmUserMapper.selectById(userId);
        String userName = wmUser.getName();
        transferDto.setAuthorName(userName);
        Integer channelId = wmNews.getChannelId();
        String channelName = wmChannelMapper.selectById(channelId).getName();
        transferDto.setChannelName(channelName);
        ResponseResult<Long> longResponseResult = articleFeign.saveArticle(transferDto);
        Long articleId = longResponseResult.getData();

        //发布时间大于当前时间则延迟发布,修改状态为9
        wmNews.setArticleId(articleId);
        wmNews.setStatus(WmNews.Status.PUBLISHED.getCode());
        wmNews.setReason("文章审核通过,已经发布");
        wmNewsMapper.updateById(wmNews);
        return  articleId;
    }

    private boolean imageVerify(WmNews wmNews, Set<String> imageSet) throws Exception {
        List<byte[]> list = imageSet.stream().map(url -> fileStorageService.downLoadFile(url)).collect(Collectors.toList());
        Map imageScan = greenImageScan.imageScan(list);
        Object suggestion = imageScan.get("suggestion");
        if (! "pass".equals(suggestion)) {
            if ("block".equals(suggestion)){
                wmNews.setStatus(WmNews.Status.FAIL.getCode());
                wmNews.setReason("图片包含违规信息:" + imageScan.get("label"));
                wmNewsMapper.updateById(wmNews);
                return false;
            }else {
                wmNews.setStatus(WmNews.Status.ADMIN_AUTH.getCode());
                wmNews.setReason("转人工审核");
                wmNewsMapper.updateById(wmNews);
                return false;
            }
        }
        return true;
    }

    private Boolean testVerify(WmNews wmNews, String contentText) throws Exception {
        Map testResult = greenTextScan.greeTextScan(contentText);
        if (! "pass".equals(testResult.get("suggestion"))) {
            //未通过设置文章状态为2
            wmNews.setStatus(WmNews.Status.FAIL.getCode());
            wmNews.setReason("文章包含违规信息:" + testResult.get("label"));
            wmNewsMapper.updateById(wmNews);
            return false;
        }
        return true;
    }

    @Autowired
    private WmSensitiveMapper wmSensitiveMapper;

    /**
     * 自管理的敏感词审核
     * @param content
     * @param wmNews
     * @return
     */
    private boolean handleSensitiveScan(String content, WmNews wmNews) {

        boolean flag = true;

        //获取所有的敏感词
        List<WmSensitive> wmSensitives = wmSensitiveMapper.selectList(Wrappers.<WmSensitive>lambdaQuery().select(WmSensitive::getSensitives));
        List<String> sensitiveList = wmSensitives.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());

        //初始化敏感词库
        SensitiveWordUtil.initMap(sensitiveList);

        //查看文章中是否包含敏感词
        Map<String, Integer> map = SensitiveWordUtil.matchWords(content);
        if(map.size() >0){
            wmNews.setStatus(WmNews.Status.FAIL.getCode());
            wmNews.setReason("文章包含违规信息:" + map.get("label"));
            wmNewsMapper.updateById(wmNews);
            flag = false;
        }

        return flag;
    }
}
